/* Copyright 203-2115 AtomWare Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * The flowing information must be keep 
 * DailyResetDateServiceImpl.java
 * business
 * 2013-1-23上午8:53:55
 * @author 屈甲康
 * QQ285799123
 * mailto:qujiakang@gmail.com
 */

package org.jackysoft.service.impl;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.jackysoft.entity.DailyResetDate;
import org.jackysoft.service.AbstractStringIdServiceImpl;
import org.jackysoft.service.DailyResetDateService;
import org.joda.time.DateTime;
import org.springframework.aop.support.AopUtils;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.ScheduledMethodRunnable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;


@Service
@Transactional
public class DailyResetDateServiceImpl 
extends AbstractStringIdServiceImpl<DailyResetDate> 
implements DailyResetDateService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1331096945208836121L;
	private TaskScheduler scheduler; 
	
	public DailyResetDateServiceImpl(){
		this.type = DailyResetDate.class;
	}
	
	
	@Override
	@SuppressWarnings("rawtypes")
	public DailyResetDate getDailyResetDate(int year, int month) {
		String hql = "from %s dr where  dr.year=%d and dr.month=%d";
		Iterator itr = query(
				String.format(hql, table(DailyResetDate.class), year, month))
				.iterate();
		return (DailyResetDate) (itr.hasNext() ? itr.next() : getDefault());
	}

	@Override
	public void setDailyResetDate(int year, int month, DateTime first,
			DateTime last) {
		DateTime dt = DateTime.now();
		if(year==0)year = dt.getYear();
		if(month==0)month = dt.getMonthOfYear();
		if(first==null){
			first = DateTime.now();
		    first = first.withDate(year,month,DailyResetDate.DEFAULT_FIRST_DAY);
		}
		if(last==null){
			last = DateTime.now();
		    last = last.withDate(year, month, DailyResetDate.DEFAULT_LAST_DAY);
		}
		DailyResetDate dr = getDailyResetDate(year, month);
		if (dr == null) {

			dr = new DailyResetDate(year, month, first, last);
		} else {
			dr.setFirstDate(first);
			dr.setLastDate(last);
		}
		getSession().saveOrUpdate(dr);
	}

	
	@Override
	public void resetDailyResetDate(int year, int month) {

		DailyResetDate dr = getDailyResetDate(year, month);
		if (dr == null)
			return;
		DateTime first = new DateTime(year, month, DailyResetDate.DEFAULT_FIRST_DAY, 0, 0, 0);
		dr.setFirstDate(first);
		DateTime last = new DateTime(year, month, DailyResetDate.DEFAULT_LAST_DAY, 0, 0, 0);
		dr.setLastDate(last);
	}

	@Override
	public void saveDailyResetDay(String id, DateTime firstDay,DateTime lastDay) {
		
		DailyResetDate obt  = get(id);
		
		boolean sameday = obt.getLastDate().isEqual(lastDay);
		
		if(!sameday){	
			
			//addScheduler(finishedService,"generateAll",lastDay);		   					
		}	
		
		obt.setFirstDate(firstDay);		
	 
		obt.setLastDate(lastDay);	
		
	}

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Collection<DailyResetDate> getDailyResetDates(int year) {
		String hql = "from %s dr where  dr.year=%d";
		List itr = query(
				String.format(hql, table(DailyResetDate.class), year)).list();
		return itr;
	}

	private ScheduledFuture addScheduler(final Object bean,String methodName,DateTime day){
		
		
        if(day.isBeforeNow())return null;
		String cron = String.format("59 59 23 %s %s ?"
				,day.getDayOfMonth()
				,day.getMonthOfYear()
				);
		
		final Class<?> targetClass = AopUtils.getTargetClass(bean);
		
		Method method = ReflectionUtils.findMethod(targetClass, methodName);
		
		Runnable runnable = new ScheduledMethodRunnable(bean, method);
		
		Trigger trigger =  new CronTrigger(cron);
		
		ScheduledFuture future =  scheduler.schedule(runnable, trigger);
		
		
		log.info("计划任务于 "+cron +"添加");
		
		return future;
		
	}

	@PostConstruct
	public void inti(){
		Collection<DailyResetDate> drds = this.gets();
	    for(DailyResetDate drd : drds){
	    	DateTime last = drd.getLastDate();
	    	if(last!=null){
	    		//addScheduler(finishedService,"generateAll",last);
	    	}
	    }
	}
	
	
	@Resource
	public void setScheduler(TaskScheduler scheduler) {
		this.scheduler = scheduler;
	}

	@Override
	@Transactional(readOnly=true)
	public DailyResetDate getDefault() {
		return getDefault(null);
	}

	
	@Override
	public boolean isEqualOrAfterResetable(){			   
	    return isEqualOrAfterResetable(null);
	    
	}
	
	@Override
	public boolean isEqualOrAfterResetable(DateTime date){
		if(date==null)date = DateTime.now().withTime(0, 0, 0, 0);
	
		DailyResetDate drd  =  getDailyResetDate(date.getYear(), date.getMonthOfYear());
		if(drd==null){
			drd = getDefault(date);
		}
		
		return date.isEqual(drd.getFirstDate()) || date.isAfter(drd.getFirstDate());
		
	}

	@Override
	@Transactional(readOnly=true)
	public DailyResetDate getDefault(DateTime date) {
		if(date==null)date = DateTime.now();
		DailyResetDate drd = new DailyResetDate(
				date.getYear(),
				date.getMonthOfYear(),
				date.withDayOfMonth(DailyResetDate.DEFAULT_FIRST_DAY),
				date.withDayOfMonth(DailyResetDate.DEFAULT_LAST_DAY)
				);
		return drd;
	}
	
}
